<template>
  <div class="canvas-container" @mousedown="startDrag" @wheel="onWheel">
    <div class="parent" :style="style">
      <draggable-resizable-vue
        v-for="item in data"
        :key="item.id"
        v-model:x="item.x"
        v-model:y="item.y"
        v-model:h="item.h"
        v-model:w="item.w"
        :class="[{ active: item.id === modelValue?.id }]"
        parent=".parent"
        :z="item.z"
        :resizable="false"
        :scale="scale"
        :draggable="edit"
        @click="selectItem(item)"
      >
        <img :src="item.imageSrc" class="w-full h-full" />
      </draggable-resizable-vue>
      <!-- 宽高 -->
      <div class="line-w">
        <div>{{ width }}px</div>
      </div>
      <div class="line-h">
        <div>{{ height }}px</div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import DraggableResizableVue from "draggable-resizable-vue3";
import { CSSProperties } from "vue";
import { DragBox } from "../data/types";
const stage = ref({
  x: 0,
  y: 0
});
const props = withDefaults(
  defineProps<{
    data: DragBox[];
    modelValue?: DragBox;
    width: number;
    height: number;
    background: string;
    edit?: boolean;
    scale: number;
  }>(),
  {
    scale: 1
  }
);
const startDrag = (de: MouseEvent) => {
  let startX = de.x;
  let startY = de.y;
  const target = de.target as HTMLElement;
  if (!target.classList.contains("canvas-container")) return;
  const mousemove = (me: MouseEvent) => {
    const offsetX = me.x - startX;
    const offsetY = me.y - startY;

    stage.value.x += offsetX;
    stage.value.y += offsetY;
    startX = me.x;
    startY = me.y;
  };
  const mouseup = () => {
    document.removeEventListener("mousemove", mousemove);
    document.removeEventListener("mouseup", mouseup);
  };
  document.addEventListener("mousemove", mousemove);
  document.addEventListener("mouseup", mouseup);
};
const emit = defineEmits(["update:modelValue", "update:scale"]);

const selectItem = (item: DragBox) => {
  emit("update:modelValue", item);
};

const style = computed((): CSSProperties => {
  const background = props.background ? `url(${props.background})` : "white";

  return {
    width: `${props.width}px`,
    height: `${props.height}px`,
    background,
    transform: `scale(${props.scale})`,
    border: "1px solid #ddd",
    left: `${stage.value.x}px`,
    top: `${stage.value.y}px`
  };
});
const onWheel = (e: WheelEvent) => {
  const delta = e.deltaY > 0 ? 0.1 : -0.1;
  const scaleDelta = Number(Math.min(Math.max(props.scale + delta, 0.2), 2).toFixed(1));
  emit("update:scale", scaleDelta);
};
</script>

<style lang="scss" scoped>
.parent {
  position: relative;
  background-color: white;
  background-repeat: no-repeat !important;
  overflow: hidden;
}

.canvas-container {
  border: 1px solid #ddd;
  flex: 1;

  background-color: #f8f8f8;
  display: flex;
  justify-content: center;
  align-items: center;
  background-size: cover;
  background-position: center;

  .active {
    outline: 2px solid rgb(240, 36, 223) !important;
  }
}

.drv {
  border: 1px solid #000;
}

.line-h {
  position: absolute;
  height: 100%;
  right: -24px;
  top: 0;
  z-index: 10;
  writing-mode: vertical-rl;
  text-orientation: upright;
  text-align: center;
}

.line-w {
  position: absolute;
  width: 100%;
  left: 0;
  top: calc(100%);
  z-index: 10;
  text-align: center;
}

.preview-image {
  background: #e9e9e9e8;
}
</style>
